package com.rickpan.service.impl;

import com.rickpan.entity.Favorite;
import com.rickpan.entity.FileInfo;
import com.rickpan.repository.FavoriteRepository;
import com.rickpan.repository.FileInfoRepository;
import com.rickpan.service.FavoriteService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 收藏文件服务实现
 * 
 * @author RickPan Team
 * @since 2024-01-06
 */
@Slf4j
@Service
@Transactional
public class FavoriteServiceImpl implements FavoriteService {

    @Autowired
    private FavoriteRepository favoriteRepository;

    @Autowired
    private FileInfoRepository fileInfoRepository;

    @Override
    public Favorite addFavorite(Long userId, Long fileId, String itemType, String category, String notes) {
        // 检查是否已经收藏
        if (favoriteRepository.existsByUserIdAndFileId(userId, fileId)) {
            String itemTypeName = "file".equals(itemType) ? "文件" : "文件夹";
            throw new RuntimeException(itemTypeName + "已经收藏过了");
        }

        // 如果没有指定category，根据文件信息自动判断
        if (category == null || category.trim().isEmpty() || "default".equals(category)) {
            category = determineFileCategory(fileId);
        }

        Favorite favorite = new Favorite();
        favorite.setUserId(userId);
        favorite.setFileId(fileId);
        favorite.setItemType(itemType != null ? itemType : "file");
        favorite.setCategory(category);
        favorite.setNotes(notes);
        favorite.setCreatedAt(LocalDateTime.now());
        favorite.setUpdatedAt(LocalDateTime.now());

        return favoriteRepository.save(favorite);
    }

    @Override
    public boolean removeFavorite(Long userId, Long fileId) {
        Optional<Favorite> favorite = favoriteRepository.findByUserIdAndFileId(userId, fileId);
        if (favorite.isPresent()) {
            favoriteRepository.delete(favorite.get());
            return true;
        }
        return false;
    }

    @Override
    public Favorite updateFavorite(Long favoriteId, String category, String notes) {
        Optional<Favorite> optionalFavorite = favoriteRepository.findById(favoriteId);
        if (optionalFavorite.isPresent()) {
            Favorite favorite = optionalFavorite.get();
            if (category != null) {
                favorite.setCategory(category);
            }
            if (notes != null) {
                favorite.setNotes(notes);
            }
            favorite.setUpdatedAt(LocalDateTime.now());
            return favoriteRepository.save(favorite);
        }
        throw new RuntimeException("收藏记录不存在");
    }

    @Override
    public boolean isFavorited(Long userId, Long fileId) {
        return favoriteRepository.existsByUserIdAndFileId(userId, fileId);
    }

    @Override
    public Page<Favorite> getFavoritesByUser(Long userId, String category, String search, Integer page, Integer size) {
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt"));

        Page<Favorite> favoritePage;
        if (search != null && !search.trim().isEmpty()) {
            // 先搜索备注和分类
            favoritePage = favoriteRepository.searchFavorites(userId, search.trim(), pageable);

            // 如果结果较少，再搜索文件名
            if (favoritePage.getContent().size() < size) {
                List<Favorite> allFavorites = favoriteRepository.findAllByUserId(userId);
                fillFileInfo(allFavorites);

                // 在内存中过滤包含搜索关键词的文件
                List<Favorite> filteredFavorites = allFavorites.stream()
                    .filter(f -> f.getFileInfo() != null &&
                                f.getFileInfo().getFileName() != null &&
                                f.getFileInfo().getFileName().toLowerCase().contains(search.trim().toLowerCase()))
                    .collect(java.util.stream.Collectors.toList());

                // 合并结果并去重
                Set<Long> existingIds = favoritePage.getContent().stream()
                    .map(Favorite::getId)
                    .collect(java.util.stream.Collectors.toSet());

                List<Favorite> combinedResults = new ArrayList<>(favoritePage.getContent());
                filteredFavorites.stream()
                    .filter(f -> !existingIds.contains(f.getId()))
                    .limit(size - favoritePage.getContent().size())
                    .forEach(combinedResults::add);

                // 创建新的Page对象
                int start = (page - 1) * size;
                int end = Math.min(start + size, combinedResults.size());
                List<Favorite> pageContent = combinedResults.subList(Math.max(0, start), end);

                favoritePage = new org.springframework.data.domain.PageImpl<>(
                    pageContent, pageable, combinedResults.size());
            }
        } else if (category != null && !category.trim().isEmpty()) {
            favoritePage = favoriteRepository.findByUserIdAndCategory(userId, category, pageable);
        } else {
            favoritePage = favoriteRepository.findByUserId(userId, pageable);
        }

        // 填充文件信息
        fillFileInfo(favoritePage.getContent());

        return favoritePage;
    }

    @Override
    public List<Favorite> getRecentFavorites(Long userId, Integer limit) {
        Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "createdAt"));
        List<Favorite> favorites = favoriteRepository.findRecentFavoritesByUserId(userId, pageable);

        // 填充文件信息
        fillFileInfo(favorites);

        return favorites;
    }

    @Override
    public List<FavoriteService.CategoryStat> getCategoryStats(Long userId) {
        List<FavoriteRepository.CategoryCount> results = favoriteRepository.getCategoryStatsByUserId(userId);
        return results.stream()
                .map(result -> new FavoriteService.CategoryStat(result.getCategory(), result.getCount()))
                .collect(java.util.stream.Collectors.toList());
    }

    @Override
    public int batchAddFavorites(Long userId, List<Long> fileIds, String category) {
        int successCount = 0;
        for (Long fileId : fileIds) {
            try {
                if (!favoriteRepository.existsByUserIdAndFileId(userId, fileId)) {
                    Favorite favorite = new Favorite();
                    favorite.setUserId(userId);
                    favorite.setFileId(fileId);
                    favorite.setCategory(category != null ? category : "default");
                    favorite.setCreatedAt(LocalDateTime.now());
                    favorite.setUpdatedAt(LocalDateTime.now());
                    favoriteRepository.save(favorite);
                    successCount++;
                }
            } catch (Exception e) {
                log.error("批量收藏失败，文件ID: {}", fileId, e);
            }
        }
        return successCount;
    }

    @Override
    public int batchRemoveFavorites(Long userId, List<Long> fileIds) {
        int successCount = 0;
        for (Long fileId : fileIds) {
            try {
                Optional<Favorite> favorite = favoriteRepository.findByUserIdAndFileId(userId, fileId);
                if (favorite.isPresent()) {
                    favoriteRepository.delete(favorite.get());
                    successCount++;
                }
            } catch (Exception e) {
                log.error("批量取消收藏失败，文件ID: {}", fileId, e);
            }
        }
        return successCount;
    }

    /**
     * 填充收藏记录的文件信息
     */
    private void fillFileInfo(List<Favorite> favorites) {
        for (Favorite favorite : favorites) {
            try {
                // 根据fileId查找文件信息
                Optional<FileInfo> fileInfoOpt = fileInfoRepository.findById(favorite.getFileId());
                if (fileInfoOpt.isPresent()) {
                    FileInfo fileInfo = fileInfoOpt.get();
                    // 只有文件未删除才设置文件信息
                    if (!fileInfo.getIsDeleted()) {
                        favorite.setFileInfo(fileInfo);
                    }
                }
            } catch (Exception e) {
                log.warn("填充文件信息失败，收藏ID: {}, 文件ID: {}", favorite.getId(), favorite.getFileId(), e);
                // 继续处理其他文件，不中断整个流程
            }
        }
    }

    /**
     * 根据文件ID自动判断文件类型分类
     */
    private String determineFileCategory(Long fileId) {
        try {
            Optional<FileInfo> fileInfoOpt = fileInfoRepository.findById(fileId);
            if (fileInfoOpt.isPresent()) {
                FileInfo fileInfo = fileInfoOpt.get();
                String fileName = fileInfo.getFileName();
                if (fileName != null) {
                    String extension = getFileExtension(fileName).toLowerCase();
                    return categorizeByExtension(extension);
                }
            }
        } catch (Exception e) {
            log.warn("无法判断文件类型，文件ID: {}", fileId, e);
        }
        return "other"; // 默认为其他类型
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) {
            return fileName.substring(lastDotIndex + 1);
        }
        return "";
    }

    /**
     * 根据文件扩展名分类
     */
    private String categorizeByExtension(String extension) {
        // 文档类型
        if (extension.matches("(doc|docx|pdf|txt|rtf|odt|pages|md|markdown)")) {
            return "document";
        }
        // 图片类型
        if (extension.matches("(jpg|jpeg|png|gif|bmp|svg|webp|ico|tiff|tif)")) {
            return "image";
        }
        // 视频类型
        if (extension.matches("(mp4|avi|mov|wmv|flv|webm|mkv|m4v|3gp|mpg|mpeg)")) {
            return "video";
        }
        // 音频类型
        if (extension.matches("(mp3|wav|flac|aac|ogg|wma|m4a)")) {
            return "audio";
        }
        // 压缩文件
        if (extension.matches("(zip|rar|7z|tar|gz|bz2)")) {
            return "archive";
        }
        // 代码文件
        if (extension.matches("(java|js|ts|py|cpp|c|h|css|html|xml|json|sql)")) {
            return "code";
        }
        // 表格文件
        if (extension.matches("(xls|xlsx|csv|ods)")) {
            return "spreadsheet";
        }
        // 演示文稿
        if (extension.matches("(ppt|pptx|odp|key)")) {
            return "presentation";
        }

        return "other";
    }
}
